package com.jplus.plugins.rpc.core;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Set;
import java.util.UUID;

import com.jplus.framework.AppConstant;
import com.jplus.framework.aop.proxy.Proxy;
import com.jplus.framework.aop.proxy.ProxyChain;
import com.jplus.framework.aop.proxy.ProxyManager;
import com.jplus.framework.bean.BeanHandle;
import com.jplus.framework.core.CharSet;
import com.jplus.framework.util.FormatUtil;
import com.jplus.plugins.rpc.Constant;
import com.jplus.plugins.rpc.annotation.RpcConsumer;
import com.jplus.plugins.rpc.bean.RpcRequest;
import com.jplus.plugins.rpc.bean.RpcResponse;
import com.jplus.plugins.rpc.bean.ZNode;
import com.jplus.plugins.rpc.impl.AgreementFactory;

/**
 * 客户端代理
 * 
 * @author Yuanqy
 *
 */
public class RpcClient {

	/**
	 * 批量创建
	 */
	public void create(Set<Field> listf) throws Exception {
		for (Field f : listf) {
			RpcConsumer rc = f.getAnnotation(RpcConsumer.class);
			BeanHandle.setBean(rc, f.getType(), create(rc, f.getType()));
		}
	}

	/**
	 * 单个创建
	 */
	@SuppressWarnings("unchecked")
	public <T> T create(final RpcConsumer rc, final Class<?> interfaceClass) throws Exception {
		// --创建消费节点
		final String ifaceName = interfaceClass.getName();
		final ZNode cliNode = new ZNode(AppConstant.CONFIG.LocalIP.getValue(), 0, 0, 0, rc.version(), rc.serviceType(), ifaceName);
		String path = FormatUtil.formatParams("{}/{}/{}/{}", Constant.ZK_REGISTRY_PATH, ifaceName, Constant.CONSUMERS,
				URLEncoder.encode(cliNode.toString(), CharSet.Default));
		ZkFactory.createPathLine(path);
		// --创建代理类
		Proxy pro = new ClientProxy(cliNode);
		return (T) ProxyManager.createProxy(interfaceClass, Arrays.asList(pro), null);
	}

	/**
	 * 客户端代理
	 */
	public class ClientProxy implements com.jplus.framework.aop.proxy.Proxy {
		private ZNode cliNode;

		public ClientProxy(ZNode cliNode) {
			this.cliNode = cliNode;
		}

		@Override
		public Object doProxy(ProxyChain proxyChain) throws Throwable {
			Method method = proxyChain.getTargetMethod();
			Object[] args = proxyChain.getMethodParams();
			RpcRequest request = new RpcRequest(); // 创建并初始化 RPC 请求
			request.setRequestId(UUID.randomUUID().toString());
			request.setIface(proxyChain.getTargetClass());
			request.setMethodName(method.getName());
			request.setParameterTypes(method.getParameterTypes());
			request.setParameters(args);
			request.setServiceType(cliNode.getServiceType());
			request.setVersion(cliNode.getVersion());
			ZNode serNode = ZkFactory.discover(cliNode); // 发现服务
			// 通过 RPC 客户端发送 RPC
			RpcResponse response = AgreementFactory.startClient(request, serNode);
			if (response.isError()) {
				throw response.getError();
			} else {
				return response.getResult();
			}
		}
	}

}